package com.eugene.element;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.eugene.entity.MvData;
import com.eugene.quant.Derivative;
import com.eugene.quant.solver.Newton;

public class Futures implements Derivative{
	private final static Logger logger = LoggerFactory.getLogger(Option.class);
	
	private FnCalendar baseDate;
	private String prodId;
	private String currency;
	
	private String underlyingId;
	private double underlyingPrice;
	
	private double strikePrice;
	private FnCalendar maturityDate;
	
	private double multiplier;
	
	private double irRate;
	private String ircId;
	private double currentPrice;
	private double irSpread;
	
	private List<MvData> rfUnderPrices = new ArrayList<MvData>();
	private List<MvData> prodUnderPrices = new ArrayList<MvData>();
	private List<MvData> currPrices = new ArrayList<MvData>();
	
	
	
	public List<MvData> getRfUnderPrices() {
		return rfUnderPrices;
	}
	public void setRfUnderPrices(List<MvData> rfUnderPrices) {
		this.rfUnderPrices = rfUnderPrices;
	}
	public List<MvData> getProdUnderPrices() {
		return prodUnderPrices;
	}
	public void setProdUnderPrices(List<MvData> prodUnderPrices) {
		this.prodUnderPrices = prodUnderPrices;
	}
	public List<MvData> getCurrPrices() {
		return currPrices;
	}
	public void setCurrPrices(List<MvData> currPrices) {
		this.currPrices = currPrices;
	}
	
	
	public Futures(){
		
	}
	public Futures(FnCalendar baseDate, String prodId, String currency
					,String underlyingId, double underlyingPrice, double strikePrice
					,FnCalendar matDate, double multiplier,String ircId
					, double irRate	, double currentPrice){
		this.baseDate = baseDate;
		this.prodId	= prodId;
		this.currency = currency;
		this.underlyingId = underlyingId;
		this.underlyingPrice = underlyingPrice;
		this.strikePrice = strikePrice;
		this.maturityDate = matDate;
		this.multiplier = multiplier;
		this.ircId = ircId;
		this.irRate = irRate;
		this.currentPrice = currentPrice;
		this.irSpread = 0.0;
	}
	
	public FnCalendar getBaseDate() {
		return baseDate;
	}
	public void setBaseDate(FnCalendar baseDate) {
		this.baseDate = baseDate;
	}
	public String getProdId() {
		return prodId;
	}
	public void setProdId(String prodId) {
		this.prodId = prodId;
	}
	
	public String getCurrency() {
		return currency;
	}
	public void setCurrency(String currency) {
		this.currency = currency;
	}
	public String getUnderlyingId() {
		return underlyingId;
	}
	public void setUnderlyingId(String underlyingId) {
		this.underlyingId = underlyingId;
	}
	public double getUnderlyingPrice() {
		return underlyingPrice;
	}
	public void setUnderlyingPrice(double underlyingPrice) {
		this.underlyingPrice = underlyingPrice;
	}
	public double getStrikePrice() {
		return strikePrice;
	}
	public void setStrikePrice(double strikePrice) {
		this.strikePrice = strikePrice;
	}
	public FnCalendar getMaturityDate() {
		return maturityDate;
	}
	public void setMaturityDate(FnCalendar maturityDate) {
		this.maturityDate = maturityDate;
	}
	
	public double getMultiplier() {
		return multiplier;
	}
	public void setMultiplier(double multiplier) {
		this.multiplier = multiplier;
	}
	public double getIrRate() {
		return irRate;
	}
	public void setIrRate(double irRate) {
		this.irRate = irRate;
	}
	
	public String getIrcId() {
		return ircId;
	}
	public void setIrcId(String ircId) {
		this.ircId = ircId;
	}
	public double getCurrentPrice() {
		return currentPrice;
	}
	public void setCurrentPrice(double currentPrice) {
		this.currentPrice = currentPrice;
	}
	public double getIrSpread() {
		Newton newton = new Newton();
		if( irSpread == 0.0){
			irSpread = newton.solvePrimeOp(this, 0.00000001, irRate, 0.0, 1.0)- irRate;
		}
		return irSpread;
	}
	public void setIrSpread(double irSpread) {
		this.irSpread = irSpread;
	}
	
	public double getRate(){
		return this.getIrRate() + getIrSpread();
	}
	
	public double getPrice(){
		double rst;
		double tf = getMaturityDate().differDays(baseDate) /(double) 365 ;
		rst = getUnderlyingPrice() * Math.exp(getRate()* tf);
		return rst;
	}
	
	public double getPrice(double irRate){
		double rst;
		double tf = getMaturityDate().differDays(baseDate) /(double) 365 ;
		rst = getUnderlyingPrice() * Math.exp(irRate * tf);
		return rst;
	}
	
	
	@Override
	public double derivative(double x){
		double tf = getMaturityDate().differDays(baseDate) /(double) 365 ;
		return getPrice(x) *  tf ;
	}

	
	@Override
	public double derivative(FnCalendar baseDate, double x) {
		return 0;
	}

	@Override
	public double derivativeSecondOp(double x) {
		return 0;
	}

	@Override
	public double derivativeSecondOp(FnCalendar baseDate, double x) {
		return 0;
	}

	@Override
	public double primeOp(double x) {
		return getPrice(x)- getCurrentPrice();
	}

	@Override
	public double primeOp(FnCalendar baseDate, double x) {
		return 0;
	}

	@Override
	public double secondOp(FnCalendar baseDate, double x) {
		return 0;
	}

}
